package net.htjs.mobile;

import java.util.ArrayList;
import java.util.List;

import net.htjs.mobile.interfaces.ChessBoardDao;
import net.htjs.mobile.player.BaseAI;
import net.htjs.mobile.player.BasePlayer;
import net.htjs.mobile.player.HumanPlayer;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
/**
 * 
 * @author Juforg
 * @author Herbert
 * 棋盘类
 */
public class ChessBoard extends View implements ChessBoardDao{

	
	//游戏状态常量
	public static final int READY = 1;				//等待开始
	public static final int RUNNING = 2;				//正在游戏中
	public static final int PLAYER_ONE_LOST = 3;		//玩家一输了
	public static final int PLAYER_TWO_LOST = 4;		//玩家二输了
	public static final boolean PLAYER1FLAG = true;
	public static final boolean PLAYER2FLAG = false;
	
	public static final int BLACK = 0;
	public static final int NEW_BLACK = 2;			//黑色棋子
	public static final int WHITE = 1;					
	public static final int NEW_WHITE = 3;			//白色棋子
	public static final int EMPTY = 4;				//无子
	
	public static int chessSize = 32;					//棋子大小
	
	private static int currentStatus = READY;			//当前状态（默认为等待开始）

	public static int maxX;							//屏幕的最大坐标（即右下角点的坐标）
	public static int maxY;
	
	public static int xOffset;							//第一点偏离左上角从像数，为了棋盘居中
	public static int yOffset;
	
	private List<Line> lines = new ArrayList<Line>();	//棋盘上所有的线
//	private List<Chess> chesses = new ArrayList<Chess>();//棋盘上所有的棋子
	public static int[][] chessArray;						 //棋盘上所有的点
	
	private BasePlayer player1 = new HumanPlayer(PLAYER1FLAG);	//玩家一(默认为人类玩家）
	private BasePlayer player2 ;						//玩家二
//	private BasePlayer currentTrun = player1;			//当前玩家 默认玩家1先
	private boolean currentPlayer = PLAYER1FLAG;		//true为玩家1 false为玩家2
	
	private Paint paint = new Paint();					//画笔对象
	
	private Bitmap[] chessColorArray = new Bitmap[4];		//不同颜色的Bigmap数组
	
	public static Chess player1newchs = null;				//玩家1前次下的棋子
	public static Chess player2newchs = null;						//玩家2前次下的棋子

	private Activity aty;
	public static RefreshHandler computerRun;
	private int delayMillis = 400 ;
	public static Long startTime;

	public ChessBoard(Context context, AttributeSet attrs) {
		super(context, attrs);
		setFocusable(true);
		Resources r = this.getContext().getResources();
		this.fillChessArrays(chessColorArray, BLACK, r.getDrawable(R.drawable.black_chess), chessSize);
		this.fillChessArrays(chessColorArray, NEW_BLACK, r.getDrawable(R.drawable.new_black_chess), chessSize);
		this.fillChessArrays(chessColorArray, WHITE, r.getDrawable(R.drawable.white_chess), chessSize);
		this.fillChessArrays(chessColorArray, NEW_WHITE, r.getDrawable(R.drawable.new_white_chess), chessSize);
		computerRun =  new RefreshHandler();
		
		//设置画线时用的颜色
        paint.setColor(Color.GRAY);
       
	}
	
	/*
	 * 初始横线和竖线的数目
	 * @see android.view.View#onSizeChanged(int, int, int, int)
	 */
	@Override
	protected void onSizeChanged(int w, int h, int oldw, int oldh) {
		maxX = (int) Math.floor(w / chessSize);
		maxY = (int) Math.floor(h / chessSize);
        BaseAI.CalculateRange.xstart = maxX-1;
        BaseAI.CalculateRange.ystart = maxY-1;
		//设置X、Y座标微调值，目的整个框居中
		 xOffset = ((w - (chessSize * maxX)) / 2);
	     yOffset = ((h - (chessSize * maxY)) / 2);
	   //创建棋盘上的线条
	     this.createLines();
	   //初始化棋盘上所有空白点
	     chessArray = new int[ChessBoard.maxX][ChessBoard.maxY];
	     BaseAI.weights = new int[ChessBoard.maxX][ChessBoard.maxY];
	     BaseAI.weights[0][0]=-1;
	     for (int i = 0; i < maxX; i++) {
			for (int j = 0; j < maxY; j++) {
				chessArray[i][j] = EMPTY;
			}
		}
	}
	
	//计算棋盘上所有的线
    private void createLines(){
    	for (int i = 0; i <= maxX; i++) {//竖线
    		lines.add(new Line(xOffset+i*chessSize-chessSize/2, yOffset, xOffset+i*chessSize-chessSize/2, yOffset+maxY*chessSize));
		}
    	for (int i = 0; i <= maxY; i++) {//横线
    		lines.add(new Line(xOffset, yOffset+i*chessSize-chessSize/2, xOffset+maxX*chessSize, yOffset+i*chessSize-chessSize/2));
		}
    }

	
	//处理触摸事件
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		//还没有开局，或者是按下事件，不处理，只处理开局后的触摸弹起事件
		if(!this.isRunning(currentStatus) ){
			Log.i("motion", "event.getAction()="+event.getAction());
			System.out.println("还没开局！");
			return true;
		}
		//是否轮到我下
		if(this.isMyTurn(player1, currentPlayer)&& MotionEvent.ACTION_UP == event.getAction()){
//			chssboddao.playerRun(player1, event); 
			this.playerRun(player1, event);
			this.refressCanvas();
			if (BaseAI.class.isAssignableFrom(player2.getClass()) && this.isMyTurn(player2, currentPlayer) && PLAYER_TWO_LOST != ChessBoard.currentStatus) {
				System.out.println("玩家2是AI");
				computerRun.computerRunAfter();
//				chssboddao.playerRun(player2, player2.run(), this);
			}
			return false;
		}else if (this.isMyTurn(player2, currentPlayer) && !BaseAI.class.isAssignableFrom(player2.getClass())) {
			this.playerRun(player2, event);
			return false;
		}
		return true;
	}
	

   
	public class RefreshHandler extends Handler {
		//这个方法主要在指定的时刻发一个消息
        public void computerRunAfter() {
        	this.removeMessages(0);
        	startTime = System.currentTimeMillis();
			Log.i("handler", "thread name:"+Thread.currentThread().getName()+"thread id:"+Thread.currentThread().getId());
        	//电脑走一步棋子
			player2.run();
        }
        
        //收到消息
        @Override
        public void handleMessage(Message msg) {
        	playerRun(player2, BaseAI.bestPoint);
        	long tmp =System.currentTimeMillis()-startTime;
        	if (tmp<delayMillis) {
				try {
					Thread.sleep(delayMillis-tmp);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
    		//刷新一下
        	refressCanvas();
        }
    };
    
    @Override
    protected void onDraw(Canvas canvas) {
    	this.drawChssboardLines(lines, canvas, paint);
    	this.drawChess(canvas, chessArray, chessColorArray, paint);
    }
    
	public static int getMaxX() {
		return maxX;
	}

	public static int getMaxY() {
		return maxY;
	}

	public static int getxOffset() {
		return xOffset;
	}

	public static int getyOffset() {
		return yOffset;
	}
	public static int getChessSize() {
		return chessSize;
	}
	
	public static int getCurrentStatus() {
		return currentStatus;
	}

	public static void setCurrentStatus(int currentStatus) {
		ChessBoard.currentStatus = currentStatus;
	}


	public boolean getCurrentPlayer() {
		return currentPlayer;
	}

	public void setCurrentPlayer(boolean currentPlayer) {
		this.currentPlayer = currentPlayer;
	}
	public void setChessArray(int[][] chessArray) {
		ChessBoard.chessArray = chessArray;
	}
	public int[][] getChessArray() {
		return chessArray;
	}

	public static Chess getPlayer1newchs() {
		return player1newchs;
	}

	public static void setPlayer1newchs(Chess player1newchs) {
		ChessBoard.player1newchs = player1newchs;
	}

	public Chess getPlayer2newchs() {
		return player2newchs;
	}

	public void setPlayer2newchs(Chess player2newchs) {
		this.player2newchs = player2newchs;
	}

	public void setPlayer2(BasePlayer player2) {
		this.player2 = player2;
	}

	public Activity getAty() {
		return aty;
	}

	public void setAty(Activity aty) {
		this.aty = aty;
	}

	
	@Override
	public void setStatus(int newStatus) {
		ChessBoard.setCurrentStatus(newStatus);
    	if(newStatus==ChessBoard.PLAYER_TWO_LOST){
			//提示玩家2输了
			//newStatus = ChessBoard.READY;
			ChessBoard.setCurrentStatus(ChessBoard.READY);
		}else if(newStatus==ChessBoard.RUNNING){
		}else if(newStatus==ChessBoard.READY){
		}else if(newStatus==ChessBoard.PLAYER_ONE_LOST){
			//提示玩家1输了
			ChessBoard.setCurrentStatus(ChessBoard.READY);
		}		
	}

	@Override
	public boolean isMyTurn(BasePlayer player, boolean currentPlayer) {
		if(player!=null){
			return player.getMyFlag()==currentPlayer;
		}
		return false;
	}
	
	@Override
	public void drawChssboardLines(List<Line> lines ,Canvas canvas, Paint paint) {
    	for (Line line : lines) {
    		canvas.drawLine(line.getXstart(), line.getYstart(), line.getXstop(), line.getYstop(), paint);
		}
	}

	@Override
	public void drawChess(Canvas canvas, int[][] chessArray,
			Bitmap[] chessColorArray, Paint paint) {
			for (int i = 0; i < ChessBoard.getMaxX(); i++) {
				for (int j = 0; j < ChessBoard.getMaxY(); j++) {
					if(chessArray[i][j ]!= EMPTY){
						int a = chessArray[i][j]-48;
						canvas.drawBitmap(chessColorArray[chessArray[i][j]],i*ChessBoard.getChessSize()
							+ChessBoard.getxOffset(),j*ChessBoard.getChessSize()+ChessBoard.getyOffset(),paint);
					
					}
				}
			}
			drawWeight(canvas, chessArray);
	}
	public void drawWeight(Canvas canvas,int[][] chessArray) {
		for (int i = BaseAI.CalculateRange.xstart; i <= BaseAI.CalculateRange.xstop; i++) {
			for (int j = BaseAI.CalculateRange.ystart; j <= BaseAI.CalculateRange.ystop; j++) {
//				if(chessArray[i][j]!='4'){
					
					drawWeight(canvas, i, j);
					
//				}
			}
		}
	}
	public void drawWeight(Canvas canvas,int i, int j){
	        Paint numPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
	        numPaint.setTextSize(10);
	        numPaint.setColor(Color.MAGENTA);
	        numPaint.setTextAlign(Align.CENTER);
	        canvas.drawText(""+BaseAI.weights[i][j], (float)(i+0.5)*ChessBoard.getChessSize(), (j+1)*ChessBoard.getChessSize(), numPaint);
//	        BaseAI.weights[i][j]= 0;
	}
	@Override
	public void restart() {
		int[][] c = new int[ChessBoard.getMaxX()][ChessBoard.getMaxY()];
	     for (int i = 0; i < ChessBoard.getMaxX(); i++) {
				for (int j = 0; j < ChessBoard.getMaxY(); j++) {
					c[i][j] = EMPTY;
				}
			}
		this.setChessArray(c);//初始化棋盘
		ChessBoard.setPlayer1newchs(null);
		this.setPlayer2newchs(null);
		BaseAI.CalculateRange.xstart = ChessBoard.maxX;
		BaseAI.CalculateRange.xstop = 0;
        BaseAI.CalculateRange.ystart = ChessBoard.maxY;
        BaseAI.CalculateRange.ystop = 0;
		this.setPlayerRun(PLAYER1FLAG);
		this.refressCanvas();
	}

	@Override
	public boolean isRunning(int currentStatus) {
		return currentStatus == ChessBoard.RUNNING;
	}

	@Override
	public synchronized void playerRun(BasePlayer player, Chess chess) {
			Log.i("old_currentPlayer", this.getCurrentPlayer()?"player1":"player2");
			if(null!=chess && this.setChess(chess, player.getMyFlag())){
				this.setCurrentPlayer(!this.getCurrentPlayer());
				if(player.hasWin(chess, player.getMyFlag(), this.getChessArray())){
					this.setStatus(player.getMyFlag()?ChessBoard.PLAYER_TWO_LOST:ChessBoard.PLAYER_ONE_LOST);
					new  AlertDialog.Builder(getAty())
					.setTitle(R.string.game_over)  
					.setMessage(player.getMyFlag()?R.string.player_two_lost:R.string.player_one_lost)  
					.setPositiveButton(R.string.restart ,
							new DialogInterface.OnClickListener() {
								public void onClick(DialogInterface dialog, int which) {
									restart();
						        	setStatus(ChessBoard.RUNNING);
									dialog.dismiss();
									}
								}
					        )  
					.setNegativeButton(R.string.return_menu , 
							new DialogInterface.OnClickListener() {
								public void onClick(DialogInterface dialog, int which) {
									getAty().finish();
									dialog.dismiss();
							}
						}
					)
					.show();
				}
				
				generateCalculateRange(chess);//产生计算边界值（提高AI效率）
				Log.i("new_currentPlayer", this.getCurrentPlayer()?"player1":"player2");
			}
			else {
				Log.i("error", "no best point ");
			}
	}

	@Override
	public void playerRun(BasePlayer player, MotionEvent event) {
		Chess chess = this.generateChess(event.getX(), event.getY());
		this.playerRun(player, chess);
	}

	@Override
	public Chess generateChess(Float x, Float y) {
		Chess  chess = new Chess(0,0);
		for(int i = 0; i <= ChessBoard.getMaxX();i++){
			if((i*ChessBoard.getChessSize()+ChessBoard.getxOffset()) <= x 
					&& x<= ((i+1)*ChessBoard.getChessSize()+ChessBoard.getxOffset())){
				chess.setX(i);
				break;
			}
		}
		for(int i = 0; i <= ChessBoard.getMaxY();i++){
			if((i*ChessBoard.getChessSize()+ChessBoard.getyOffset()) <= y 
					&& y<= ((i+1)*ChessBoard.getChessSize()+ChessBoard.getyOffset())){
				chess.setY(i);
				break;
			}
		}
		return chess;
	}


	@Override
	public void refressCanvas() {
		this.invalidate();		
	}

	@Override
	public void fillChessArrays(Bitmap[] chessColorArray, int color,
			Drawable drawable, int chessSize) {
		 Bitmap bitmap = Bitmap.createBitmap(chessSize, chessSize, Bitmap.Config.ARGB_8888);
	        Canvas canvas = new Canvas(bitmap);
	        drawable.setBounds(0, 0, chessSize, chessSize);
	        drawable.draw(canvas);
	        chessColorArray[color] = bitmap;
	}

	@Override
	public void setPlayerRun(BasePlayer player) {
		this.setCurrentPlayer(player.getMyFlag());
	}
	
	@Override
	public void setPlayerRun(boolean playerFlag) {
		this.setCurrentPlayer(playerFlag);
	}

	@Override
	public boolean setChess(Chess chess, boolean playerFlag) {
		if (EMPTY == this.getChessArray()[chess.getX()][chess.getY()]) {
			if (ChessBoard.PLAYER1FLAG == playerFlag) {
				if (null != ChessBoard.getPlayer1newchs()) {
					this.getChessArray()[ChessBoard.getPlayer1newchs()
							.getX()][ChessBoard.getPlayer1newchs().getY()] = ChessBoard.BLACK;
				}
				ChessBoard.setPlayer1newchs(chess);
				this.getChessArray()[chess.getX()][chess.getY()] = ChessBoard.NEW_BLACK;
			} else if (ChessBoard.PLAYER2FLAG == playerFlag) {
				if (null != this.getPlayer2newchs()) {
					this.getChessArray()[this.getPlayer2newchs()
							.getX()][this.getPlayer2newchs().getY()] = ChessBoard.WHITE;
				}
				chess.setFlag(ChessBoard.NEW_BLACK);
				this.setPlayer2newchs(chess);
				this.getChessArray()[chess.getX()][chess.getY()] = ChessBoard.NEW_WHITE;
			}
			return true;
		}
		return false;
			
	}

	public void generateCalculateRange(Chess chess){
		if(chess.getX()<=BaseAI.CalculateRange.xstart){
			if ((chess.getX()-1)>=0) {
				BaseAI.CalculateRange.xstart=chess.getX()-1;
			} else {
				BaseAI.CalculateRange.xstart=chess.getX();
			}
		}
		if (chess.getX()>=BaseAI.CalculateRange.xstop ) {
			if ((chess.getX()+1)<=ChessBoard.maxX) {
				BaseAI.CalculateRange.xstop=chess.getX()+1;
			} else {
				BaseAI.CalculateRange.xstop=chess.getX();
			}
		}
		if(chess.getY()<=BaseAI.CalculateRange.ystart){
			if ((chess.getY()-1)>=0) {
				BaseAI.CalculateRange.ystart=chess.getY()-1;
			} else {
				BaseAI.CalculateRange.ystart=chess.getY();
			}
		}
		if (chess.getY()>=BaseAI.CalculateRange.ystop) {
			if ((chess.getY()+1)<=ChessBoard.maxY) {
				BaseAI.CalculateRange.ystop=chess.getY()+1;
			} else {
				BaseAI.CalculateRange.ystop=chess.getY();
			}
		}
		Log.i("calculateRang", "x:"+BaseAI.CalculateRange.xstart+"-->"+BaseAI.CalculateRange.xstop);
		Log.i("calculateRang", "Y:"+BaseAI.CalculateRange.ystart+"-->"+BaseAI.CalculateRange.ystop);
	}
}
